package com.qianda.qdminiapp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qianda.qdminiapp.common.constant.CommonConstant;
import com.qianda.qdminiapp.common.exception.ExceptionCode;
import com.qianda.qdminiapp.common.exception.SimpleException;
import com.qianda.qdminiapp.common.util.DateUtils;
import com.qianda.qdminiapp.common.util.RandomUtil;
import com.qianda.qdminiapp.config.CompanyProperties;
import com.qianda.qdminiapp.config.WxpayProperties;
import com.qianda.qdminiapp.dao.activity.QqdRedpacketAmtDetailDao;
import com.qianda.qdminiapp.dao.activity.QqdRedpacketDrawLogDao;
import com.qianda.qdminiapp.dao.activity.QqdStoreRedpacketProbDao;
import com.qianda.qdminiapp.dao.device.QqdStoreDao;
import com.qianda.qdminiapp.dao.order.QqdOrderTowelDao;
import com.qianda.qdminiapp.dao.user.QqdUserDao;
import com.qianda.qdminiapp.domain.data.QqdRedpacketActivityData;
import com.qianda.qdminiapp.domain.data.WithdrawHandlerData;
import com.qianda.qdminiapp.domain.dto.DrawRedpacketDto;
import com.qianda.qdminiapp.domain.model.activity.QqdRedpacketActivity;
import com.qianda.qdminiapp.dao.activity.QqdRedpacketActivityDao;
import com.qianda.qdminiapp.domain.model.activity.QqdRedpacketAmtDetail;
import com.qianda.qdminiapp.domain.model.activity.QqdRedpacketDrawLog;
import com.qianda.qdminiapp.domain.model.activity.QqdStoreRedpacketProb;
import com.qianda.qdminiapp.domain.model.device.QqdStore;
import com.qianda.qdminiapp.domain.model.order.QqdOrderTowel;
import com.qianda.qdminiapp.domain.model.user.QqdUser;
import com.qianda.qdminiapp.service.QqdRedpacketActivityService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qianda.qdminiapp.service.order.BalancePaymentImpl;
import com.qianda.qdminiapp.service.pay.WxPayment;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * <p>
 * 红包活动 服务实现类
 * </p>
 *
 * @author cw
 * @since 2020-07-15
 */
@Service
@EnableConfigurationProperties({ CompanyProperties.class , WxpayProperties.class})
public class QqdRedpacketActivityServiceImpl extends ServiceImpl<QqdRedpacketActivityDao, QqdRedpacketActivity> implements QqdRedpacketActivityService {

    private static Logger LOGGER = LoggerFactory.getLogger(QqdRedpacketActivityServiceImpl.class);

    @Autowired
    private QqdRedpacketActivityDao qqdRedpacketActivityDao;

    @Autowired
    private QqdRedpacketAmtDetailDao qqdRedpacketAmtDetailDao;

    @Autowired
    private QqdRedpacketDrawLogDao qqdRedpacketDrawLogDao;

    @Autowired
    private QqdStoreDao qqdStoreDao;

    @Autowired
    private QqdStoreRedpacketProbDao qqdStoreRedpacketProbDao;

    @Autowired
    private CompanyProperties companyProperties;

    @Autowired
    private QqdOrderTowelDao qqdOrderTowelDao;

    @Autowired
    private QqdUserDao qqdUserDao;

    @Autowired
    private WxpayProperties wxpayProperties;

    @Override
    @Transactional
    public QqdRedpacketActivityData getRedpacketActivity(Long userId, Long orderId) {

        LOGGER.info("开始获取随机红包！");
        //获取订单
        QqdOrderTowel qqdOrderTowel = qqdOrderTowelDao.selectById(orderId);

        //已完成的订单且必须为微信支付才有红包
        if(qqdOrderTowel.getOrderStatus() != CommonConstant.OrderOutTowelStatus.ORDER_OUT_TOWEL_STATUS_FINISH
                || qqdOrderTowel.getOrderPayStatus() != CommonConstant.PayStatus.PAY_STATUS_PAYED
                || qqdOrderTowel.getOrderPayType() != CommonConstant.PayType.PAY_TYPE_WX){
            LOGGER.info("订单不满足，获取红包失败！");
            return new QqdRedpacketActivityData(0);
        }

        //获取正在上架的红包活动
        QueryWrapper<QqdRedpacketActivity> qqdRedpacketActivityQueryWrapper = new QueryWrapper<>();
        qqdRedpacketActivityQueryWrapper.eq("status",CommonConstant.Status.STATUS_NORMAL);
        qqdRedpacketActivityQueryWrapper.eq("activity_status",CommonConstant.ActivityStatus.ACTIVITY_STATUS_UP);
        LocalDateTime nowTime =  LocalDateTime.now();
        qqdRedpacketActivityQueryWrapper.le("start_time", nowTime);
        qqdRedpacketActivityQueryWrapper.ge("end_time",nowTime);
        qqdRedpacketActivityQueryWrapper.eq("company_id",companyProperties.getId());
        List<QqdRedpacketActivity> qqdRedpacketActivities = qqdRedpacketActivityDao.selectList(qqdRedpacketActivityQueryWrapper);
        if(qqdRedpacketActivities.size()<1){
            LOGGER.info("未获取到正在上架的红包活动或红包已过期！");
            return new QqdRedpacketActivityData(0);
        }
        QqdRedpacketActivity qqdRedpacketActivity = qqdRedpacketActivities.get(0);
        if(!(qqdRedpacketActivity.getDrawCount() <qqdRedpacketActivity.getRedCount())){
            LOGGER.info("红包已领完！");
            return new QqdRedpacketActivityData(0);
        }

        //获取门店
        QqdStore qqdStore = qqdStoreDao.selectById(qqdOrderTowel.getStoreId());
        Long bindRedpacketId = qqdStore.getBindRedpacketId();
        if(bindRedpacketId == 0 || bindRedpacketId != qqdRedpacketActivity.getId()){
            LOGGER.info("门店没有参与活动！");
            return new QqdRedpacketActivityData(0);
        }

        //判断门店当天获取的次数
        if(qqdRedpacketActivity.getStoreLimitCount() != null && qqdRedpacketActivity.getStoreLimitCount() != 0){
            Long currentDayStoreCount = qqdRedpacketDrawLogDao.getCurrentDayStoreCount(qqdRedpacketActivity.getId(), qqdStore.getId(), DateUtils.getNowStringDate());
            if(currentDayStoreCount>=qqdRedpacketActivity.getStoreLimitCount()){
                LOGGER.info("门店当天次数已用完");
                return new QqdRedpacketActivityData(0);
            }
        }

        //判断用户当天获取次数
        if(qqdRedpacketActivity.getUserLimitCount()!= null && qqdRedpacketActivity.getUserLimitCount() != 0){
            Long currentDayUserCount = qqdRedpacketDrawLogDao.getCurrentDayUserCount(qqdRedpacketActivity.getId(), userId, DateUtils.getNowStringDate());
            if(currentDayUserCount>=qqdRedpacketActivity.getUserLimitCount()){
                LOGGER.info("用户当天次数已用完");
                return new QqdRedpacketActivityData(0);
            }

        }

        //获取门店的概率
        QueryWrapper<QqdStoreRedpacketProb> qqdStoreRedpacketProbQueryWrapper = new QueryWrapper<>();
        qqdStoreRedpacketProbQueryWrapper.eq("store_id",qqdOrderTowel.getStoreId());
        qqdStoreRedpacketProbQueryWrapper.eq("redpacket_id",qqdRedpacketActivity.getId());
        QqdStoreRedpacketProb qqdStoreRedpacketProb = qqdStoreRedpacketProbDao.selectOne(qqdStoreRedpacketProbQueryWrapper);
        //概率
        Integer prob = 100;
        if(qqdStoreRedpacketProb !=null){
            prob = qqdStoreRedpacketProb.getValue();
        }
        //随机获取0到100里的数
        int ramdomV = (int) (Math.random() * 100);
        if(ramdomV>prob){
            LOGGER.info("随机未中奖");
            return new QqdRedpacketActivityData(0);
        }

        QueryWrapper<QqdRedpacketAmtDetail> qqdRedpacketAmtDetailQueryWrapper = new QueryWrapper<>();
        qqdRedpacketAmtDetailQueryWrapper.eq("redpacket_id",qqdRedpacketActivity.getId());
        qqdRedpacketAmtDetailQueryWrapper.eq("lock_status",CommonConstant.LockStatus.LOCK_STATUS_YES);
        qqdRedpacketAmtDetailQueryWrapper.eq("user_id",userId);
        List<QqdRedpacketAmtDetail> qqdRedpacketAmtDetails = qqdRedpacketAmtDetailDao.selectList(qqdRedpacketAmtDetailQueryWrapper);
        if(qqdRedpacketAmtDetails.size()>0){
            LOGGER.info("该用户已有红包详情，本次发放失败！");
            return new QqdRedpacketActivityData(0);
        }

        QqdRedpacketAmtDetail redpacketAmtDetail = getRedpacketAmtDetail(qqdRedpacketActivity.getId(), userId);
        if(redpacketAmtDetail==null){
            LOGGER.info("红包详情已发送完！");
            return new QqdRedpacketActivityData(0);
        }
        if(redpacketAmtDetail.getAmt().compareTo(new BigDecimal("0.3"))<0){
            LOGGER.info("红包金额太小，不能发放");
            qqdRedpacketAmtDetailDao.deleteById(redpacketAmtDetail.getId());
            return new QqdRedpacketActivityData(0);
        }

        //十分钟未领取，取消锁定
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                qqdRedpacketAmtDetailDao.cancelLockStatus(redpacketAmtDetail.getId(),userId);
                }
        },600000);

        return new QqdRedpacketActivityData(1,qqdRedpacketActivity.getId(),qqdRedpacketActivity.getName(),redpacketAmtDetail.getId(),redpacketAmtDetail.getAmt());
    }

    /**
     * 获取红包详情
     * @param qqdRedpacketActivityId
     * @param userId
     * @return
     */
    private QqdRedpacketAmtDetail getRedpacketAmtDetail(Long qqdRedpacketActivityId,Long userId){

        //获取红包金额详情
        QueryWrapper<QqdRedpacketAmtDetail> qqdRedpacketAmtDetailQueryWrapper = new QueryWrapper<>();
        qqdRedpacketAmtDetailQueryWrapper.eq("redpacket_id",qqdRedpacketActivityId);
        qqdRedpacketAmtDetailQueryWrapper.eq("lock_status",CommonConstant.LockStatus.LOCK_STATUS_NO);
        List<QqdRedpacketAmtDetail> qqdRedpacketAmtDetails = qqdRedpacketAmtDetailDao.selectList(qqdRedpacketAmtDetailQueryWrapper);
        if(qqdRedpacketAmtDetails.size()<1){
            return null;
        }

        //随机获取角标
        int index = (int) (Math.random() * (qqdRedpacketAmtDetails.size()));
        QqdRedpacketAmtDetail qqdRedpacketAmtDetail = qqdRedpacketAmtDetails.get(index);
        //这里通过递归解决并发问题
        int updateCount = qqdRedpacketAmtDetailDao.setLockStatus(userId, qqdRedpacketAmtDetail.getId());
        if(updateCount<1){
            getRedpacketAmtDetail(qqdRedpacketActivityId,userId);
        }else{
            return qqdRedpacketAmtDetail;
        }
        return null;
    }

    @Override
    @Transactional
    public QqdRedpacketActivityData drawRedpacket(DrawRedpacketDto drawRedpacketDto,Long userId) {
        LOGGER.info("开始领取红包！");
        //获取用户信息
        QqdUser qqdUser = qqdUserDao.selectById(userId);
        if(StringUtils.isBlank(qqdUser.getUserOpenId())){
            throw new SimpleException(ExceptionCode.EX_DEVICE_ACCOUNT_ERROR);
        }

        //获取红包详情
        QqdRedpacketAmtDetail qqdRedpacketAmtDetail = qqdRedpacketAmtDetailDao.selectById(drawRedpacketDto.getRedpacketAmtDetailId());
        if(qqdRedpacketAmtDetail==null || qqdRedpacketAmtDetail.getLockStatus() != CommonConstant.LockStatus.LOCK_STATUS_YES || qqdRedpacketAmtDetail.getUserId() == null || qqdRedpacketAmtDetail.getUserId() != userId){
            throw new SimpleException(ExceptionCode.EX_REDPACKET_OVER_TIME);
        }

        //订单
        QqdOrderTowel qqdOrderTowel = qqdOrderTowelDao.selectById(drawRedpacketDto.getOrderId());

        //门店
        QqdStore qqdStore = qqdStoreDao.selectById(qqdOrderTowel.getStoreId());

        //创建记录
        QqdRedpacketDrawLog qqdRedpacketDrawLog = new QqdRedpacketDrawLog();
        String orderNo = RandomUtil.getId();
        qqdRedpacketDrawLog.setDrawNo(orderNo);
        qqdRedpacketDrawLog.setRedpacketActivityId(drawRedpacketDto.getRedpacketActivityId());
        qqdRedpacketDrawLog.setUserId(userId);
        qqdRedpacketDrawLog.setNickname(qqdUser.getNickname());
        qqdRedpacketDrawLog.setAvatar(qqdUser.getAvatar());
        qqdRedpacketDrawLog.setRedpacketActivityName(drawRedpacketDto.getRedpacketActivityName());
        qqdRedpacketDrawLog.setStoreId(qqdOrderTowel.getStoreId());
        qqdRedpacketDrawLog.setStoreName(qqdStore.getStoreName());
        qqdRedpacketDrawLog.setDeviceId(qqdOrderTowel.getOrderDeviceId());
        qqdRedpacketDrawLog.setRedpacketAmtDetailId(qqdRedpacketAmtDetail.getId());
        qqdRedpacketDrawLog.setOrderId(drawRedpacketDto.getOrderId());
        qqdRedpacketDrawLog.setDrawAmt(qqdRedpacketAmtDetail.getAmt());
        qqdRedpacketDrawLog.setDrawTime(LocalDateTime.now());
        qqdRedpacketDrawLogDao.insert(qqdRedpacketDrawLog);

        WithdrawHandlerData withdrawHandlerData = (new WxPayment()).companyPay(qqdUser, qqdRedpacketDrawLog, wxpayProperties);
        //测试
       // WithdrawHandlerData withdrawHandlerData = new WithdrawHandlerData();
        //withdrawHandlerData.setResultCode("SUCCESS");

        qqdRedpacketActivityDao.addOneDrawCount(qqdRedpacketAmtDetail.getRedpacketId());

        if("SUCCESS".equals(withdrawHandlerData.getResultCode())){
            qqdRedpacketAmtDetailDao.deleteById(qqdRedpacketAmtDetail.getId());
        }

        return new QqdRedpacketActivityData(qqdRedpacketDrawLog.getDrawAmt());
    }
}
